package com.hw.shortlink.project.mq;

import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.hw.shortlink.project.common.constant.ShortLinkConstants;
import com.hw.shortlink.project.dao.entity.*;
import com.hw.shortlink.project.dao.mapper.*;
import com.hw.shortlink.project.dto.mq.StatsMessageDto;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.ExchangeTypes;
import org.springframework.amqp.rabbit.annotation.*;
import org.springframework.amqp.support.converter.MessageConversionException;
import org.springframework.aop.framework.AopContext;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;

import static com.hw.shortlink.project.common.constant.MqConstants.*;

@Component
@RequiredArgsConstructor
@Slf4j
public class ShortLinkStatsListener {
    private final LinkAccessStatsMapper linkAccessStatsMapper;
    private final LinkLocaleStatsMapper linkLocaleStatsMapper;
    private final LinkOsStatsMapper linkOsStatsMapper;
    private final LinkBrowserStatsMapper linkBrowserStatsMapper;
    private final LinkAccessLogsMapper linkAccessLogsMapper;
    private final LinkDeviceStatsMapper linkDeviceStatsMapper;
    private final LinkNetworkStatsMapper linkNetworkStatsMapper;

    @Value("${shortlink.locale.stats.key}")
    private String amapKey;


    @RabbitListener(bindings = @QueueBinding(
            value = @Queue(name = STATS_QUEUE_NAME, arguments = @Argument(name = "x-query-mode", value = "lazy")),
            key = STATS_DIRECT_KEY,
            exchange = @Exchange(name = STATS_EXCHANGE_NAME, type = ExchangeTypes.DIRECT
            )
    ))
    public void listenStatsMessage(String message) {
        try {
            StatsMessageDto statsMessageDto = JSON.parseObject(message, StatsMessageDto.class);

            log.info(statsMessageDto.toString());
            ShortLinkStatsListener o = (ShortLinkStatsListener) AopContext.currentProxy();
            o.shortLinkStats(statsMessageDto);
        } catch (Exception  e) {
            //throw new RuntimeException(e);
            e.printStackTrace();
            throw new MessageConversionException("短链接统计消息消费失败，移出消息队列，不再试错");
        }


    }

    @Transactional
    public void shortLinkStats(StatsMessageDto statsMessageDto) {
        String fullShortUrl = statsMessageDto.getFullShortUrl();
        String ip = statsMessageDto.getIp();
        String os = statsMessageDto.getOs();
        String browser = statsMessageDto.getBrowser();
        String device = statsMessageDto.getDevice();
        String network = statsMessageDto.getNetwork();
        String uv = statsMessageDto.getUv();
        Boolean uvFirstFlag = statsMessageDto.getUvFirstFlag();
        Boolean uipFirstFlag = statsMessageDto.getUipFirstFlag();
        LocalDateTime localDateTime = LocalDateTime.now();
        Date now = Date.from(localDateTime.atZone(ZoneId.systemDefault()).toInstant());


        //统计uv，pv，uip
        LinkAccessStats linkAccessStats = LinkAccessStats.builder()
                .hour(localDateTime.getHour())
                .fullShortUrl(fullShortUrl)
                .weekday(localDateTime.getDayOfWeek().getValue())
                .date(now)
                .pv(1)
                .uv(uvFirstFlag ? 1 : 0)
                .uip(uipFirstFlag ? 1 : 0)
                .build();
        linkAccessStatsMapper.shortLinkAccessStats(linkAccessStats);

        //统计地区
        Map<String, Object> param = new HashMap<>();
        param.put("key", amapKey);
        //todo 需要获取真实ip
        param.put("ip", ip);
        String resultJson = HttpUtil.get(ShortLinkConstants.AMAP_REMOTE_URL, param);

        JSONObject jsonObject = JSON.parseObject(resultJson);
        String infoCode = jsonObject.getString("infocode");
        String province = jsonObject.getString("province");
        String adCode = jsonObject.getString("adcode");
        String city = jsonObject.getString("city");
        LinkLocaleStats linkLocaleStats = LinkLocaleStats.builder()
                .fullShortUrl(fullShortUrl)
                .date(now)
                .cnt(1)
                .province(Objects.equals(province, "[]") ? "未知" : province)
                .city(Objects.equals(city, "[]") ? "未知" : city)
                .country("中国")
                .adcode(Objects.equals(adCode, "[]") ? "未知" : adCode)
                .build();
        linkLocaleStatsMapper.shortLinkLocaleStats(linkLocaleStats);


        //统计操作系统
        LinkOsStats linkOsStats = LinkOsStats.builder()
                .fullShortUrl(fullShortUrl)
                .date(now)
                .cnt(1)
                .os(os)
                .build();
        linkOsStatsMapper.shortLinkOsStats(linkOsStats);

        //统计浏览器
        LinkBrowserStats linkBrowserStats = LinkBrowserStats.builder()
                .fullShortUrl(fullShortUrl)
                .date(now)
                .cnt(1)
                .browser(browser)
                .build();
        linkBrowserStatsMapper.shortLinkBrowserStats(linkBrowserStats);

        //统计设备类型
        LinkDeviceStats linkDeviceStats = LinkDeviceStats.builder()
                .fullShortUrl(fullShortUrl)
                .date(now)
                .cnt(1)
                .device(device)
                .build();
        linkDeviceStatsMapper.shortLinkDeviceStats(linkDeviceStats);

        //统计网络类型
        LinkNetworkStats linkNetworkStats = LinkNetworkStats.builder()
                .fullShortUrl(fullShortUrl)
                .date(now)
                .cnt(1)
                .network(network)
                .build();
        linkNetworkStatsMapper.shortLinkNetworkStats(linkNetworkStats);

        //记录每一次访问的日志
        LinkAccessLogs linkAccessLogs = LinkAccessLogs.builder()
                .fullShortUrl(fullShortUrl)
                .user(uv)
                .ip(ip)
                .os(os)
                .browser(browser)
                .network(network)
                .device(device)
                .locale(linkLocaleStats.getCountry() + linkLocaleStats.getProvince() + linkLocaleStats.getCity())
                .build();
        linkAccessLogsMapper.insert(linkAccessLogs);
    }

}


